#include <lcir/ADT/OwningRefVector.h>
#include <lcir/IR/Expression.h>
#include <lcir/IR/Op.h>
#include <lcir/IR/Operand.h>
#include <lcir/IR/Prototype.h>
#include <lcir/IR/VReg.h>
#include <lcir/IR/Value.h>
#include <lcir/Utils/Utils.h>
#include <lcir/ADT/Range.h>
#include <lcir/IR/Lambda.h>
#include <lcir/IR/ValuePrinter.h>
#include <lcir/IR/Constant.h>

#include <memory>
#include <sstream>
#include <stdexcept>
#include <vector>


namespace lcir {
Expression::~Expression() { clearOperands(); }
Expression::Expression(Op *op, const std::vector<Prototype *> retProtos, const std::vector<Value *> &operandVals) {
  this->op.reset(op);
  addResults(retProtos);
  addOperands(operandVals);
}
// Value -> Expression -> Op
// add -
//     |     
// add - add
Constant *Expression::tryFold() {
  std::vector<Value*> foldValues; 
  for(auto val: getOperandValues()) {
    auto *c = val->tryFold();
    foldValues.push_back(val->tryFold());
  }
  return op->tryFold(foldValues);
}
Op *Expression::getOp() const { return op.get(); }
OpInstance *Expression::getOpInstance() const { return op->getInstance(); }

Operand *Expression::getOperand(size_t idx) const {
  [[unlikely]] if (idx >= operands.size())
    throw std::runtime_error("operand size error");
  return &operands[idx];
}

Value *Expression::getOperandValue(size_t idx) const {
  [[unlikely]] if (idx >= operands.size())
    throw std::runtime_error("operand size error");
  return operands[idx].getValue();
}
std::vector<Value *> Expression::getOperandValues() const {
  auto ret = mapToVector<Value *>(operands, [](const Operand &i) { return i.getValue(); });
  return ret;
}

void Expression::setOperand(size_t idx, Value *val) {
  [[unlikely]] if (idx >= operands.size())
    throw std::runtime_error("operand size error");
  auto &operand = operands[idx];
  operand.removeFromParent();
  operand.setValue(val);
}
std::vector<Operand *> Expression::getOperands() const {
  auto ret = mapToVector<Operand *>(operands, [](Operand &i) { return &i; });
  return ret;
}

void Expression::addOperand(Value *val) {
  auto *operand = new Operand();
  operand->setValue(val);
  operand->setExpression(this);
  operands.pushBack(operand);
}

void Expression::addOperands(const std::vector<Value *> &operandVals) {
  for (auto *v : operandVals) {
    addOperand(v);
  }
}

void Expression::addResults(const std::vector<Prototype *> &protos) {
  for (auto *p : protos) {
    auto *reg = new VReg(std::unique_ptr<Prototype>(p), this);
    results.pushBack(reg);
  }
}

std::unique_ptr<Expression> Expression::removeFromLambda() {
  removeFromParent();
  parent = nullptr;
  return std::unique_ptr<Expression>(this);
}

void Expression::eraseFromLambda() { eraseFromParent(); }
Lambda *Expression::getLambda() const {
  if (!getParent()) return nullptr;
  return static_cast<Lambda *>(getParent());
}
Value *Expression::findTopParent() const {
  Value *root = getLambda();
  if (!root) {
    return nullptr;  // 如果根节点为空，直接返回
  }

  Value *p = root->getDefExprParent();
  while (p && p->getDefExprParent()) {
    root = p;
    p = p->getDefExprParent();
  }
  return root;  // 返回最顶层父节点
}

std::vector<Value *> Expression::getResults() const {
  std::vector<Value *> ret;
  for (auto &v : results) {
    ret.push_back(&v);
  }
  return ret;
}
Value *Expression::getResult() const {
  if (results.empty()) return nullptr;
  return &results[0];
}
Value *Expression::getResult(size_t idx) const {
  if (idx >= results.size()) return nullptr;
  return &results[idx];
}
Prototype *Expression::getResultProto() const {
  if (results.empty()) return nullptr;
  return results[0].getProto();
}
Expression *Expression::insertBack(std::unique_ptr<Expression> expr) {
  auto *l = getLambda();
  if (!l) throw std::runtime_error("insertPoint is not in a lambda");
  return l->insertExprAfter(this, std::move(expr));
}
Expression *Expression::insertFront(std::unique_ptr<Expression> expr) {
  auto *l = getLambda();
  if (!l) throw std::runtime_error("insertPoint is not in a lambda");
  return l->insertExpr(this, std::move(expr));
}

size_t Expression::getDepth() const {
  auto *lambda = getLambda();
  if (lambda) return lambda->getDepth() + 1;
  return 0;
}
std::string Expression::print() const {
  // 找到Parent
  Value *root = findTopParent();
  ValuePrinter vp(root);
  // 首先打印result
  return vp.print(this);
}

void Expression::dump() const { std::cout << print() << "\n"; }

void Expression::setParent(LambdaBase *parent) {
  if (this->parent)
    throw std::runtime_error("expression cannot set parent twice!");
  else
    this->parent = parent;
}

void Expression::handleOperandValues(const std::vector<Value *> &operandVals) {
  for (auto *v : operandVals) {
    if (auto *l = v->dyn_cast<Lambda>()) {
      l->setDefExpr(this);
    }
  }
}
void Expression::clearOperands() {
  // 把他的oeprand都取下来
  for (auto &operand : operands) {
    operand.removeFromParent();
  }
}
}  // namespace lcir